#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;

Semaphore semaphore_bee;
Semaphore semaphore_ant;
int buffer = 10;
int cheese_burger;
int honey;
void a_bee(void *arg)
{
    int delay = 0xfffffff;
    int num = 0;
    while(1)
    {
    	if(delay==0)
    	{
    	    semaphore_bee.P();
    	    honey += 1;
	    printf("honey bee: I start to gather honeys, there are %d honeys now.\n", honey); 	    
	    semaphore_ant.V();
	    delay = 0xfffffff;
	 }
	 delay --;
    }
    
}

void a_ant(void *arg)
{
	int delay = 0x8ffffff;
	int sub = 0;
    while(1)
    {
    	if(delay == 0)
    	{
	   semaphore_ant.P();
	    printf("ant   : I come to buy 1 honey!\n");	    
	    honey -= 1;
	    printf(" There left %d honeys!\n",honey);
	    semaphore_bee.V();
	    delay = 0x8ffffff;
	 }
	 delay --;
    }
}

void first_thread(void *arg)
{
    // 第1个线程不可以返回
    stdio.moveCursor(0);
    for (int i = 0; i < 25 * 80; ++i)
    {
        stdio.print(' ');
    }
    stdio.moveCursor(0);

    cheese_burger = 0;
    honey = 0;
    semaphore_bee.initialize(buffer);
    semaphore_ant.initialize(0);
    programManager.executeThread(a_bee, nullptr, "second thread", 1);
    programManager.executeThread(a_ant, nullptr, "third thread", 1);

    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}
